package com.devilvan.betrice.aiqicha.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.devilvan.betrice.aiqicha.dto.*;
import com.devilvan.betrice.aiqicha.po.*;
import com.devilvan.betrice.aiqicha.service.*;
import com.devilvan.betrice.aiqicha.vo.*;
import com.devilvan.betrice.common.BetriceResultCode;
import com.devilvan.betrice.common.BetriceResultVo;
import com.devilvan.betrice.exception.BetriceException;
import com.devilvan.betrice.request.BetriceHttpBuilder;
import com.devilvan.betrice.request.component.HttpClientComponent;
import com.devilvan.betrice.request.pojo.BetriceHttpClient;
import com.devilvan.betrice.util.UCopy;
import com.devilvan.betrice.util.UEmpty;
import com.devilvan.betrice.util.UString;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author Evad.Wu
 * @Description 爱企查 控制器
 * @date 2022-09-23
 */
@RestController
@RequestMapping(value = "aiqichaController")
@Tag(name = "爱企查 控制器")
@SuppressWarnings(value = "unused")
public class AiqichaController {
    private static final String REFERER_SUFFIX = "https://aiqicha.baidu.com/company_detail_";
    private static final String URL_SUFFIX = "https://aiqicha.baidu.com/detail/entBasicAllDataAjax?pid=";

    @Resource(name = "httpClientComponent")
    private HttpClientComponent httpClientComponent;

    @Resource(name = "aiqichaHeaderServiceImpl")
    private AiqichaHeaderService aiqichaHeaderService;
    @Resource(name = "aiqichaShareholdersServiceImpl")
    private AiqichaShareholdersService aiqichaShareholdersService;
    @Resource(name = "aiqichaDirectorsServiceImpl")
    private AiqichaDirectorsService aiqichaDirectorsService;
    @Resource(name = "aiqichaInvestRecordServiceImpl")
    private AiqichaInvestRecordService aiqichaInvestRecordService;
    @Resource(name = "aiqichaLegalDocServiceImpl")
    private AiqichaLegalDocService aiqichaLegalDocService;
    @Resource(name = "aiqichaOpenNoticeServiceImpl")
    private AiqichaOpenNoticeService aiqichaOpenNoticeService;
    @Resource(name = "aiqichaAbnormalServiceImpl")
    private AiqichaAbnormalService aiqichaAbnormalService;
    @Resource(name = "aiqichaTradeMarkServiceImpl")
    private AiqichaTradeMarkService aiqichaTradeMarkService;
    @Resource(name = "aiqichaPatentServiceImpl")
    private AiqichaPatentService aiqichaPatentService;
    @Resource(name = "aiqichaLicenseServiceImpl")
    private AiqichaLicenseService aiqichaLicenseService;
    @Resource(name = "aiqichaTenderBiddingServiceImpl")
    private AiqichaTenderBiddingService aiqichaTenderBiddingService;

    /**
     * 通过企业PID进行数据采集
     *
     * @param pid 企业PID
     * @return 形式回调
     */
    @Operation(summary = "通过企业PID进行数据采集")
    @GetMapping(value = "doAiqicha")
    public BetriceResultVo<AiqichaHeaderPo> doAiqicha(@RequestParam("pid") Long pid) {
        BetriceResultVo<AiqichaHeaderPo> betriceResultVo;
        Map<String, String> header = Map.of("Referer", REFERER_SUFFIX + pid);
        String url = URL_SUFFIX + pid;
        BetriceHttpClient betriceHttpClient = BetriceHttpBuilder.create()
                .setHttpRequest(RequestMethod.GET, url)
                .setHeaders(header)
                .build();
        String json = httpClientComponent.doExecute(betriceHttpClient);
        betriceResultVo = this.doAiqicha(pid, json);
        return betriceResultVo;
    }

    /**
     * 测试：通过报文解析
     *
     * @param request 测试报文
     * @return 形式回调
     */
    @Operation(summary = "测试：通过报文解析")
    @PostMapping(value = "doAiqichaOne")
    public BetriceResultVo<AiqichaHeaderPo> doAiqichaOne(@RequestBody String request) {
        Long pid = 524458332013L;
        BetriceResultVo<AiqichaHeaderPo> betriceResultVo = this.doAiqicha(pid, request);
        return betriceResultVo;
    }

    /**
     * 核心方法：采集爱企查数据
     *
     * @param pid     企业ID
     * @param request 报文
     * @return 形式返回
     */
    private BetriceResultVo<AiqichaHeaderPo> doAiqicha(Long pid, String request) {
        BetriceResultVo<AiqichaHeaderPo> betriceResultVo = new BetriceResultVo<>();
        try {
            JSONObject data = JSONObject.parseObject(request).getJSONObject("data");
            // 解析
            AiqichaHeaderVo aiqichaHeaderVo = this.parseHeaderVo(data);
            List<AiqichaShareholdersVo> aiqichaShareholdersVoList = this.parseElement(data, AiqichaShareholdersVo.class, "shareholdersData");
            List<AiqichaDirectorsVo> aiqichaDirectorsVoList = this.parseElement(data, AiqichaDirectorsVo.class, "directorsData");
            List<AiqichaInvestRecordVo> aiqichaInvestRecordVoList = this.parseElement(data, AiqichaInvestRecordVo.class, "investRecordData");
            List<AiqichaLegalDocVo> aiqichaLegalDocVoList = this.parseElement(data, AiqichaLegalDocVo.class, "lawWenshu");
            List<AiqichaAbnormalVo> aiqichaAbnormalVoList = this.parseElement(data, AiqichaAbnormalVo.class, "abnormal");
            List<AiqichaOpenNoticeVo> aiqichaOpenNoticeVoList = this.parseElement(data, AiqichaOpenNoticeVo.class, "opennotice");
            List<AiqichaTradeMarkVo> aiqichaTradeMarkVoList = this.parseElement(data, AiqichaTradeMarkVo.class, "mark");
            List<AiqichaPatentVo> aiqichaPatentVoList = this.parseElement(data, AiqichaPatentVo.class, "patent");
            List<AiqichaLicenseVo> aiqichaLicenseVoList = this.parseElement(data, AiqichaLicenseVo.class, "license");
            List<AiqichaTenderBiddingVo> aiqichaTenderBiddingVoList = this.parseElement(data, AiqichaTenderBiddingVo.class, "tenderbidding");
            // 组装
            // 1. 基本信息
            AiqichaHeaderDto aiqichaHeaderDto = this.copyHeaderVo2Dto(pid, aiqichaHeaderVo);
            // 2. 股东信息
            List<AiqichaShareholdersDto> aiqichaShareholdersDtoList = this.copyShareholdersVo2Dto(pid, aiqichaShareholdersVoList);
            // 3. 主要人员信息
            List<AiqichaDirectorsDto> aiqichaDirectorsDtoList = this.copyDirectorsVo2Dto(pid, aiqichaDirectorsVoList);
            // 4. 对外投资信息
            List<AiqichaInvestRecordDto> aiqichaInvestRecordDtoList = this.copyInvestRecordVo2Dto(pid, aiqichaInvestRecordVoList);
            // 5. 裁决文书信息
            List<AiqichaLegalDocDto> aiqichaLegalDocDtoList = this.copyLegalDocVo2Dto(pid, aiqichaLegalDocVoList);
            // 6. 开庭公告信息
            List<AiqichaOpenNoticeDto> aiqichaOpenNoticeDtoList = this.copyOpenNoticeVo2Dto(pid, aiqichaOpenNoticeVoList);
            // 7. 企业经营异常信息
            List<AiqichaAbnormalDto> aiqichaAbnormalDtoList = this.copyAbnormalVo2Dto(pid, aiqichaAbnormalVoList);
            // 8. 商标信息
            List<AiqichaTradeMarkDto> aiqichaTradeMarkDtoList = this.copyTradeMarkVo2Dto(pid, aiqichaTradeMarkVoList);
            // 9. 专利信息
            List<AiqichaPatentDto> aiqichaPatentDtoList = this.copyPatentVo2Dto(pid, aiqichaPatentVoList);
            // 10. 行政许可信息
            List<AiqichaLicenseDto> aiqichaLicenseDtoList = this.copyLicenseVo2Dto(pid, aiqichaLicenseVoList);
            // 11. 招/投标信息
            List<AiqichaTenderBiddingDto> aiqichaTenderBiddingDtoList = this.copyTenderBiddingVo2Dto(pid, aiqichaTenderBiddingVoList);
            // 保存
            AiqichaHeaderPo aiqichaHeaderPo = aiqichaHeaderService.saveUpdate(aiqichaHeaderDto);
            List<AiqichaShareholdersPo> aiqichaShareholdersPoList =
                    aiqichaShareholdersService.saveUpdateBatch(aiqichaShareholdersDtoList);
            List<AiqichaDirectorsPo> aiqichaDirectorsPoList =
                    aiqichaDirectorsService.saveUpdateBatch(aiqichaDirectorsDtoList);
            List<AiqichaInvestRecordPo> aiqichaInvestRecordPoList =
                    aiqichaInvestRecordService.saveUpdateBatch(aiqichaInvestRecordDtoList);
            List<AiqichaLegalDocPo> aiqichaLegalDocPoList =
                    aiqichaLegalDocService.saveUpdateBatch(aiqichaLegalDocDtoList);
            List<AiqichaOpenNoticePo> aiqichaOpenNoticePoList =
                    aiqichaOpenNoticeService.saveUpdateBatch(aiqichaOpenNoticeDtoList);
            List<AiqichaAbnormalPo> aiqichaAbnormalPoList =
                    aiqichaAbnormalService.saveUpdateBatch(aiqichaAbnormalDtoList);
            List<AiqichaTradeMarkPo> aiqichaTradeMarkPoList =
                    aiqichaTradeMarkService.saveUpdateBatch(aiqichaTradeMarkDtoList);
            List<AiqichaPatentPo> aiqichaPatentPoList =
                    aiqichaPatentService.saveUpdateBatch(aiqichaPatentDtoList);
            List<AiqichaLicensePo> aiqichaLicensePoList =
                    aiqichaLicenseService.saveUpdateBatch(aiqichaLicenseDtoList);
            List<AiqichaTenderBiddingPo> aiqichaTenderBiddingPoList =
                    aiqichaTenderBiddingService.saveUpdateBatch(aiqichaTenderBiddingDtoList);
            betriceResultVo.result(BetriceResultCode.SUCCESS_200, "操作成功！");
        } catch (Exception e) {
            e.printStackTrace();
            betriceResultVo.result(BetriceResultCode.FAILED_500, "操作失败：" + e);
        }
        return betriceResultVo;
    }

    /**
     * 招/投标信息 VO转Dto
     *
     * @param pid                        企业ID
     * @param aiqichaTenderBiddingVoList 招/投标信息VO集合
     * @return 招/投标信息VO
     */
    private List<AiqichaTenderBiddingDto> copyTenderBiddingVo2Dto(Long pid, List<AiqichaTenderBiddingVo> aiqichaTenderBiddingVoList) {
        return aiqichaTenderBiddingVoList.stream().map(m -> {
            StringBuilder sb = new StringBuilder();
            // 投标公司
            String tenderBidderNameJoin = null;
            List<BiddersVo> tenderList = m.getTender();
            if (UEmpty.isNotEmpty(tenderList)) {
                List<String> tenderBidderNameList = tenderList.stream().map(BiddersVo::getName).toList();
                tenderBidderNameJoin = UString.join(tenderBidderNameList, ",");
            }
            // 中标公司
            String winnerBidderNameJoin = null;
            List<BiddersVo> winnerList = m.getWinner();
            if (UEmpty.isNotEmpty(winnerList)) {
                List<String> winnerBidderNameList = winnerList.stream().map(BiddersVo::getName).toList();
                winnerBidderNameJoin = UString.join(winnerBidderNameList, ",");
            }
            AiqichaTenderBiddingDto aiqichaTenderBiddingDto = new AiqichaTenderBiddingDto();
            UCopy.fullCopy(m, aiqichaTenderBiddingDto);
            aiqichaTenderBiddingDto.setPid(pid);
            aiqichaTenderBiddingDto.setTender(tenderBidderNameJoin);
            aiqichaTenderBiddingDto.setWinner(winnerBidderNameJoin);
            return aiqichaTenderBiddingDto;
        }).toList();
    }

    /**
     * 行政许可信息 VO转Dto
     *
     * @param pid                  企业ID
     * @param aiqichaLicenseVoList 行政许可信息VO集合
     * @return 行政许可信息VO
     */
    private List<AiqichaLicenseDto> copyLicenseVo2Dto(Long pid, List<AiqichaLicenseVo> aiqichaLicenseVoList) {
        return UCopy.fullCopyCollections(aiqichaLicenseVoList, AiqichaLicenseDto.class)
                .stream().peek(m -> m.setPid(pid)).toList();
    }

    /**
     * 专利信息 VO转Dto
     *
     * @param pid                 企业ID
     * @param aiqichaPatentVoList 专利信息VO集合
     * @return 专利信息VO
     */
    private List<AiqichaPatentDto> copyPatentVo2Dto(Long pid, List<AiqichaPatentVo> aiqichaPatentVoList) {
        return UCopy.fullCopyCollections(aiqichaPatentVoList, AiqichaPatentDto.class)
                .stream().peek(m -> m.setPid(pid)).toList();
    }

    /**
     * 商标信息 VO转Dto
     *
     * @param pid                    企业ID
     * @param aiqichaTradeMarkVoList 商标信息VO集合
     * @return 商标信息VO
     */
    private List<AiqichaTradeMarkDto> copyTradeMarkVo2Dto(Long pid, List<AiqichaTradeMarkVo> aiqichaTradeMarkVoList) {
        return UCopy.fullCopyCollections(aiqichaTradeMarkVoList, AiqichaTradeMarkDto.class)
                .stream().peek(m -> m.setPid(pid)).toList();
    }

    /**
     * 经营异常信息 VO转Dto
     *
     * @param pid                   企业ID
     * @param aiqichaAbnormalVoList 经营异常信息VO集合
     * @return 经营异常信息VO
     */
    private List<AiqichaAbnormalDto> copyAbnormalVo2Dto(Long pid, List<AiqichaAbnormalVo> aiqichaAbnormalVoList) {
        return UCopy.fullCopyCollections(aiqichaAbnormalVoList, AiqichaAbnormalDto.class)
                .stream().peek(m -> m.setPid(pid)).toList();
    }

    /**
     * 开庭公告信息 VO转Dto
     *
     * @param pid                     企业ID
     * @param aiqichaOpenNoticeVoList 开庭公告信息VO集合
     * @return 开庭公告信息VO
     */
    private List<AiqichaOpenNoticeDto> copyOpenNoticeVo2Dto(Long pid, List<AiqichaOpenNoticeVo> aiqichaOpenNoticeVoList) {
        return aiqichaOpenNoticeVoList.stream().map(m -> {
            StringBuilder sb = new StringBuilder();
            RelatedCompaniesVo relatedCompaniesVo = Optional.ofNullable(m.getRelatedCompaniesVo()).orElseGet(RelatedCompaniesVo::new);
            // 原告
            String plaintiffJoin = null;
            RoleNamesVo plaintiff = Optional.ofNullable(relatedCompaniesVo.getPlaintiff()).orElseGet(RoleNamesVo::new);
            String plaintiffRole = plaintiff.getRole();
            if (UEmpty.isNotEmpty(plaintiffRole)) {
                String nameArrjoin = UString.join(plaintiff.getNameArr(), ",");
                plaintiffJoin = plaintiffRole + "：" + Optional.ofNullable(nameArrjoin).orElse("");
            }
            // 被告
            String defendantJoin = null;
            RoleNamesVo defendant = Optional.ofNullable(relatedCompaniesVo.getDefendant()).orElseGet(RoleNamesVo::new);
            String defendantRole = defendant.getRole();
            if (UEmpty.isNotEmpty(defendantRole)) {
                String nameArrjoin = UString.join(defendant.getNameArr(), ",");
                defendantJoin = defendantRole + "：" + Optional.ofNullable(nameArrjoin).orElse("");
            }
            // 第三人
            String thirdPartyJoin = null;
            RoleNamesVo thirdParty = Optional.ofNullable(relatedCompaniesVo.getThirdParty()).orElseGet(RoleNamesVo::new);
            String thirdPartyRole = thirdParty.getRole();
            if (UEmpty.isNotEmpty(thirdPartyRole)) {
                String nameArrjoin = UString.join(thirdParty.getNameArr(), ",");
                thirdPartyJoin = thirdPartyRole + "：" + Optional.ofNullable(nameArrjoin).orElse("");
            }
            if (UEmpty.isNotEmpty(plaintiffJoin)) {
                sb.append(plaintiffJoin).append("\n");
            }
            if (UEmpty.isNotEmpty(defendantJoin)) {
                sb.append(defendantJoin).append("\n");
            }
            if (UEmpty.isNotEmpty(thirdPartyJoin)) {
                sb.append(thirdPartyJoin);
            }
            String relatedCompanies = sb.toString();
            // 组装
            AiqichaOpenNoticeDto aiqichaOpenNoticeDto = new AiqichaOpenNoticeDto();
            UCopy.fullCopy(m, aiqichaOpenNoticeDto, "relatedCompaniesVo");
            aiqichaOpenNoticeDto.setPid(pid);
            aiqichaOpenNoticeDto.setRelatedCompanies(relatedCompanies);
            return aiqichaOpenNoticeDto;
        }).toList();
    }

    /**
     * 裁决文书信息 VO转Dto
     *
     * @param pid                   企业ID
     * @param aiqichaLegalDocVoList 裁决文书信息VO集合
     * @return 裁决文书信息VO
     */
    private List<AiqichaLegalDocDto> copyLegalDocVo2Dto(Long pid, List<AiqichaLegalDocVo> aiqichaLegalDocVoList) {
        return UCopy.fullCopyCollections(aiqichaLegalDocVoList, AiqichaLegalDocDto.class)
                .stream().peek(m -> m.setPid(pid)).toList();
    }

    /**
     * 对外投资信息 VO转Dto
     *
     * @param pid                       企业ID
     * @param aiqichaInvestRecordVoList 对外投资信息VO集合
     * @return 对外投资信息VO
     */
    private List<AiqichaInvestRecordDto> copyInvestRecordVo2Dto(Long pid, List<AiqichaInvestRecordVo> aiqichaInvestRecordVoList) {
        return UCopy.fullCopyCollections(aiqichaInvestRecordVoList, AiqichaInvestRecordDto.class)
                .stream().peek(m -> m.setPid(pid)).toList();
    }

    /**
     * 主要人员信息 VO转Dto
     *
     * @param pid                    企业ID
     * @param aiqichaDirectorsVoList 主要人员信息VO集合
     * @return 主要人员信息VO集合
     */
    private List<AiqichaDirectorsDto> copyDirectorsVo2Dto(Long pid, List<AiqichaDirectorsVo> aiqichaDirectorsVoList) {
        return UCopy.fullCopyCollections(aiqichaDirectorsVoList, AiqichaDirectorsDto.class)
                .stream().peek(m -> {
                    m.setPid(pid);
                    m.setPersonLink("https://aiqicha.baidu.com" + m.getPersonLink());
                }).toList();
    }

    /**
     * 股东信息 VO转Dto
     *
     * @param pid                       企业ID
     * @param aiqichaShareholdersVoList 股东信息VO集合
     * @return 股东信息VO集合
     */
    private List<AiqichaShareholdersDto> copyShareholdersVo2Dto(Long pid, List<AiqichaShareholdersVo> aiqichaShareholdersVoList) {
        return UCopy.fullCopyCollections(aiqichaShareholdersVoList, AiqichaShareholdersDto.class)
                .stream().peek(m -> m.setPid(pid)).toList();
    }

    /**
     * 基本信息 VO转Dto
     *
     * @param pid             企业ID
     * @param aiqichaHeaderVo 基本信息VO
     * @return 基本信息VO
     */
    private AiqichaHeaderDto copyHeaderVo2Dto(Long pid, AiqichaHeaderVo aiqichaHeaderVo) {
        AiqichaHeaderDto aiqichaHeaderDto = new AiqichaHeaderDto();
        UCopy.fullCopy(aiqichaHeaderVo, aiqichaHeaderDto, "insuranceInfo");
        InsuranceInfoVo insuranceInfoVo = aiqichaHeaderVo.getInsuranceInfoVo();
        aiqichaHeaderDto.setPid(pid);
        aiqichaHeaderDto.setInsuranceNum(insuranceInfoVo.getInsuranceNum());
        aiqichaHeaderDto.setInsuranceYear(insuranceInfoVo.getInsuranceYear());
        return aiqichaHeaderDto;
    }

    /**
     * 采集报文中的基本信息部分，判断不能为空
     *
     * @param data 关键字集合的上级
     * @return 基本信息
     */
    private AiqichaHeaderVo parseHeaderVo(JSONObject data) {
        AiqichaHeaderVo aiqichaHeaderVo = data.getJSONObject("basicData")
                .toJavaObject(AiqichaHeaderVo.class);
        aiqichaHeaderVo = Optional.ofNullable(aiqichaHeaderVo)
                .orElseThrow(() -> new BetriceException("基本信息不能为空！"));
        return aiqichaHeaderVo;
    }

    /**
     * 大坑：getJSONArray().toJavaList，会导致@JSONField中的deserializeUsing属性失效，不走自定义的反序列化方法
     * 将报文中的数据按照关键字，转换成不同类型的集合
     *
     * @param data    关键字集合的上级
     * @param type    转换后的类型
     * @param keyword 关键字
     * @param <T>     泛型
     * @return 转换后的集合
     */
    private <T> List<T> parseElement(JSONObject data, Class<T> type, String keyword) {
        List<T> list = new ArrayList<>();
        try {
            JSONObject keywordLevel = data.getJSONObject(keyword);
            if (null == keywordLevel) {
                return list;
            }
            String jsonArrayString = keywordLevel.getJSONArray("list").toJSONString();
            list = JSONArray.parseArray(jsonArrayString, type);
            for (T t : list) {
                System.out.println(t);
            }
            System.out.println();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

}
